package DEEPERsource.DEEPERsource.source.controllers;

import java.io.FileNotFoundException;
import java.io.PrintStream;

import preprocessing.SimplePreprocessor;
import corpus.Text;
import corpus.ppi.CorpusFactory;
import deeper.Interaction;
import deeper.InteractionType;

import statistics.Counter;
import statistics.DepTreeAnalyzer;
import statistics.FreqMap;

public class StatisticsCollector {

	private Text loadDataset(String sourceXML, String serialDir){
		CorpusFactory cFactory = new CorpusFactory();
		Text corpus = cFactory.getCorpusFromPPIXML(sourceXML, new SimplePreprocessor());
		corpus.parse(null,"serialized",serialDir);
		return corpus;
	}
	
	public void runFrequencyStat(PrintStream out, Text corpus){
		DepTreeAnalyzer dta = new DepTreeAnalyzer();
		FreqMap<String> trueWordFreq = new FreqMap<String>();
		FreqMap<String> trueDepFreq = new FreqMap<String>();
		FreqMap<String> falseWordFreq = new FreqMap<String>();
		FreqMap<String> falseDepFreq = new FreqMap<String>();
		for(Interaction i : corpus.interactions()){
			if(i.depPath == null){
				continue;
			}
			FreqMap<String> wordFreq = dta.wordFrequency(i.depPath);
			FreqMap<String> depFreq = dta.depFrequency(i.depPath);
			if(wordFreq.get("ccoterm0")==null || wordFreq.get("ccoterm1")==null){
				System.err.println(i.sentence);
				System.err.println(i.depPath.toString());
			}
			if(i.status.equals(InteractionType.FALSE)){
				falseWordFreq.putAll(wordFreq);
				falseDepFreq.putAll(depFreq);
			}else{
				trueWordFreq.putAll(wordFreq);
				trueDepFreq.putAll(depFreq);
			}
		}	
		out.append("Words in true intreactions :\t");
		out.append(trueWordFreq.toString());
		out.append("\nDependencies in true intreactions :\t");
		out.append(trueDepFreq.toString());
		out.append("\nWords in false intreactions :\t");
		out.append(falseWordFreq.toString());
		out.append("\nDependencies in false intreactions :\t");
		out.append(falseDepFreq.toString());
	}
	
	//counts a number of grammar relation subsequences of different lengths
	public void depFreqN(PrintStream out, Text corpus){
		DepTreeAnalyzer dta = new DepTreeAnalyzer();
		FreqMap<String> trueDepFreq = new FreqMap<String>();
		FreqMap<String> falseDepFreq = new FreqMap<String>();
		for(Interaction i : corpus.interactions()){
			if(i.depPath == null){
				continue;
			}
			FreqMap<String> depFreq = dta.depFrequencyN(i.depPath,2);
			if(i.status.equals(InteractionType.FALSE)){
				falseDepFreq.putAll(depFreq);
			}else{
				trueDepFreq.putAll(depFreq);
			}
		}
		out.append("\nDependencies length 2 in true intreactions :\t");
		out.append(trueDepFreq.toString());
		out.append("\nDependencies length 2 in false intreactions :\t");
		out.append(falseDepFreq.toString());
		
		trueDepFreq.clear();
		falseDepFreq.clear();
		
		for(Interaction i : corpus.interactions()){
			if(i.depPath == null){
				continue;
			}
			FreqMap<String> depFreq = dta.depFrequencyN(i.depPath,3);
			if(i.status.equals(InteractionType.FALSE)){
				falseDepFreq.putAll(depFreq);
			}else{
				trueDepFreq.putAll(depFreq);
			}
		}
		out.append("\nDependencies length 3 in true intreactions :\t");
		out.append(trueDepFreq.toString());
		out.append("\nDependencies length 3 in false intreactions :\t");
		out.append(falseDepFreq.toString());
	}
	
	public void nullPaths(PrintStream out, Text corpus){
		int trueNull = 0, falseNull = 0;
		for(Interaction i : corpus.interactions()){
			if(i.depPath == null){
				if(i.status.equals(InteractionType.REAL)){
					trueNull++;	
				}else{
					falseNull++;
				}
			}
		}
		out.append("Undefined true paths : "+trueNull);
		out.append("\nUndefined false paths : "+falseNull);
	}
	
	public void countInteractions(PrintStream out, Text corpus){
		int _true = 0, _false = 0;
		for(Interaction i : corpus.interactions()){
			if(i.status.equals(InteractionType.REAL)){
				_true++;
			}else{
				_false++;
			}
		}
		out.append("True interactions : "+_true);
		out.append("\nFalse interactions : "+_false);
	}
	
	//count sentences
	public void tmp(PrintStream out, Text corpus){
		int trueSent = 0, falseSent = 0;
		String curSent = "";
		for(Interaction i : corpus.interactions()){
			String sent = i.getClearSentence();
			boolean changed = false;
			if(!curSent.equals(sent)){
				changed = true;
				curSent = sent;
			}
			if(i.status.equals(InteractionType.REAL)){
				if(changed)
					trueSent++;
			}
		}
		curSent = "";
		for(Interaction i : corpus.interactions()){
			String sent = i.getClearSentence();
			boolean changed = false;
			if(!curSent.equals(sent)){
				changed = true;
				curSent = sent;
			}
			if(i.status.equals(InteractionType.FALSE)){
				if(changed)
					falseSent++;
			}
		}
		out.append("Sentences that contains at least one interaction : "+trueSent);
		out.append("\nSentences that does not contain any interactions : "+falseSent);
	}
	
	//count the number of protein names, that are coupled with another word
	public void coupledTerms(PrintStream out, Text corpus){
		DepTreeAnalyzer dta = new DepTreeAnalyzer();
		FreqMap<String> trueTermFreq = new FreqMap<String>();
		FreqMap<String> falseTermFreq = new FreqMap<String>();
		for(Interaction i : corpus.interactions()){
			if(i.depPath == null){
				continue;
			}
			FreqMap<String> wordFreq = dta.wordFrequency(i.depPath);
			for(String key : wordFreq.keySet()){
				if(key.contains("ccoterm0")||key.contains("ccoterm1")){
					String newKey = key.replaceAll("ccoterm\\d","ccoterm");
					if(i.status.equals(InteractionType.REAL)){
						trueTermFreq.put(newKey, wordFreq.get(key));
					}else{
						falseTermFreq.put(newKey, wordFreq.get(key));
					}
				}
			}
		}
		out.append(trueTermFreq.toString());
		out.append("\n\n\n\n");
		out.append(falseTermFreq.toString());	
	}
	
	public void runRootFreq(PrintStream out, Text corpus){
		DepTreeAnalyzer dta = new DepTreeAnalyzer();
		FreqMap<String> trueRootFreq = new FreqMap<String>();
		FreqMap<String> falseRootFreq = new FreqMap<String>();
		for(Interaction i : corpus.interactions()){
			if(i.depPath == null){
				continue;
			}
			if(i.status.equals(InteractionType.REAL)){
				String[] roots = dta.root(i.depPath);
				for(String root : roots)
					trueRootFreq.put(root, 1);
			}else{
				String[] roots = dta.root(i.depPath);
				for(String root : roots)
					falseRootFreq.put(root, 1);
			}			
		}	
		out.append("Roots for true intreactions :\t");
		out.append(trueRootFreq.toString());
		out.append("\nRoots for false intreactions :\t");
		out.append(falseRootFreq.toString());
	}
	
	public void runCounterStat(PrintStream out, Text corpus){
		Counter c = new Counter();
		int real = c.countByInteractionType(corpus.interactions(), InteractionType.REAL);
		int _false = c.countByInteractionType(corpus.interactions(), InteractionType.FALSE);
		out.append("True intreactions number:\t");
		out.append(Integer.toString(real));
		out.append("\nFalse intreactions number:\t");
		out.append(Integer.toString(_false));
	}
	
	public void run(PrintStream writer, Text corpus, String type){
		if(type.equals("frequency")){
			runFrequencyStat(writer, corpus);
		}else if(type.equals("counter")){
			runCounterStat(writer, corpus);
		}else if(type.equals("rootFreq")){
			runRootFreq(writer, corpus);
		}else if(type.equals("tmp")){
			tmp(writer, corpus);
		}
	}
	
	/**
	 * 
	 * @param args
	 * -xml resource/aimed.xml
	 * -serialized resource/sparse/aimed
	 * -output resource/aimedStat (opt)
	 * -statType counter|frequency|rootFreq|tmp
	 */
	public static void main(String[] args){
		String sourceXML = "", serialDir = "", file = "", type = "";
		for(int i = 0; i< args.length; i++){
			if(args[i].equals("-xml")){
				sourceXML = args[++i];
			}
			if(args[i].equals("-serialized")){
				serialDir = args[++i];
			}
			if(args[i].equals("-output")){
				file = args[++i];
			}
			if(args[i].equals("-statType")){
				type = args[++i];
			}
		}
		StatisticsCollector sc = new StatisticsCollector();
		Text corpus = sc.loadDataset(sourceXML, serialDir);
		if(file.equals("")){
			sc.run(System.out, corpus, type);
		}else{
			PrintStream out = null;
			try {
				out = new PrintStream(file);
				sc.run(out, corpus, type);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}finally{
				if(out!=null){
					out.close();
				}			
			}
		}		
	}
}
